package com.bnz.security.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private DataSource dataSource;
    //1. 系统自带的
//    @Override
//    protected void configure(HttpSecurity http) throws Exception{
//        http.formLogin()        //使用系统自带的登录表单
//                .successForwardUrl("/success")      //登录成功后跳转到的页面
//                .and()
//                .authorizeRequests()                //除登录相关的其他请求
//                .anyRequest()
//                .authenticated();                   //都要经过认证才能访问
//    }


//    //2. 定制化登录表
//    @Override
//    protected void configure(HttpSecurity http) throws Exception {
//        http.formLogin()
//                .loginPage("/login.html")               //登录页面
//                .loginProcessingUrl("/login")           //登录处理页（自己定义名称，由系统完成）
//                .successForwardUrl("/success")           //登录成功后跳转的页面
//                .and()
//                .authorizeRequests()
//                .antMatchers("/login.html","/webjars/**") //要放行的页面
//                .permitAll()
//                .anyRequest()                           //任意其他请求
//                .authenticated()                        //一律需要认证
//                .and()
//                .csrf()                                 //禁用csrf功能
//                .disable();
//
//    }
//    //3. 认证和授权
//    @Override
//    protected void configure(HttpSecurity http) throws Exception {
//        http.exceptionHandling().accessDeniedPage("/unauth.html").and()
//                .formLogin()
//                .loginPage("/login.html")               //登录页面
//                .loginProcessingUrl("/login")           //登录处理页（自己定义名称，由系统完成）
//                .successForwardUrl("/success")           //登录成功后跳转的页面
//                .and()
//                .authorizeRequests()
//                .antMatchers("/user/findAll")
//                //.hasAuthority("user")                     //是否在MyDetailService中的权限列表中有此权限
//                //.hasAnyAuthority("admin11","aa","bb")     //此权限列表中是否在MyDetailService中的权限列表中有其中一个权限
//                //.hasRole("user")         //是否在MyDetailService中的角色列表中有此角色
//                .hasAnyRole("aa","admin","cc")       //是否在MyDetailService中的角色列表中有此任意一个角色
//                .anyRequest()
//                .authenticated()
//                .and()
//                .csrf()                                 //禁用csrf功能
//                .disable();
//
//    }

    //4. 通过注解认证
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.exceptionHandling().accessDeniedPage("/unauth.html").and()
                .formLogin()
                .loginPage("/login.html")               //登录页面
                .loginProcessingUrl("/login")           //登录处理页（自己定义名称，由系统完成）
                .successForwardUrl("/success")           //登录成功后跳转的页面
                .and()
                .authorizeRequests().anyRequest().authenticated()
                .and()
                .rememberMe()                            //配置记住我的功能
                .tokenValiditySeconds(100)              //token到期时间：以s为单位
                .tokenRepository(tokenRepos())          //配置记住我功能数据源
                .userDetailsService(userDetailsService)
                .and()
                .csrf()                                 //禁用csrf功能
                .disable();

    }

    //5. 设置token数据源
    @Bean
    public PersistentTokenRepository tokenRepos() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        //设置数据源
        jdbcTokenRepository.setDataSource(dataSource);
        jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }

    //6. 设置密码加密器
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
         auth.userDetailsService(userDetailsService).passwordEncoder(encoder());
    }

    //7. 指定放行的url路径
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/login.html","/webjars/**");
    }

    //8. 指定加密方式
    @Bean
    public PasswordEncoder encoder() {
        return new BCryptPasswordEncoder();
    }
}
